﻿using Nasty.Core.Log;
using Quartz;
using Quartz.Impl.Matchers;
using System.Text.Json;

namespace Nasty.QuartzModule
{

    public class QuartzDynamicService
    {
        private readonly ISchedulerFactory _schedulerFactory;
        private readonly ILogger<QuartzDynamicService> _logger;

        public QuartzDynamicService(ISchedulerFactory schedulerFactory, ILogger<QuartzDynamicService> logger)
        {
            _schedulerFactory = schedulerFactory;
            _logger = logger;
        }

        /// <summary>
        /// 添加任务
        /// </summary>
        public async Task<bool> AddJobAsync(
            QuartzTask.QuartzTask task,
            Type type)
        {
            try
            {
                var scheduler = await _schedulerFactory.GetScheduler();
                var jobKey = new JobKey(task.Name, task.Group);

                // 创建 JobDataMap 并填充数据
                var jobDataMap = new JobDataMap { ["Task"] = task };

                // 创建 JobDetail
                var jobDetail = JobBuilder.Create(type)
                    .WithIdentity(jobKey)
                    .UsingJobData(jobDataMap)
                    .Build();

                var trigger = TriggerBuilder.Create()
                      .WithIdentity($"{task.Name}-trigger", task.Group)
                      .WithCronSchedule(task.Cron, cs => cs
                           .InTimeZone(TimeZoneInfo.Local) // 设置时区
                           .WithMisfireHandlingInstructionDoNothing() // 关键：错过的执行什么都不做
                       )
                      .ForJob(jobKey)
                      .Build();

                await scheduler.ScheduleJob(jobDetail, trigger);
                //_logger.LogInformation("通用任务 {JobName} 添加成功", jobName);
                SerilogLogger.LogInfo($"定时任务 {task.Name} 添加成功");
                return true;
            }
            catch (Exception ex)
            {
                //_logger.LogError(ex, "添加通用任务失败: {JobName}", jobName);
                SerilogLogger.LogError($"定时任务 {task.Name} 添加失败 {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 暂停一个 Job
        /// </summary>
        public async Task<bool> PauseJobAsync(QuartzTask.QuartzTask task)
        {
            try
            {
                var scheduler = await _schedulerFactory.GetScheduler();
                var jobKey = new JobKey(task.Name, task.Group);
                await scheduler.PauseJob(jobKey);
                //_logger.LogInformation("Job {JobName} paused successfully.", jobName);

                SerilogLogger.LogInfo($"定时任务 {task.Name} 暂停成功");
                return true;
            }
            catch (Exception ex)
            {
                //_logger.LogError(ex, "Failed to pause job {JobName}", jobName);
                SerilogLogger.LogError($"定时任务 {task.Name} 暂停失败 {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 删除一个 Job
        /// </summary>
        public async Task<bool> DeleteJobAsync(QuartzTask.QuartzTask task)
        {
            try
            {
                var scheduler = await _schedulerFactory.GetScheduler();
                var jobKey = new JobKey(task.Name, task.Group);
                var result = await scheduler.DeleteJob(jobKey);
                //_logger.LogInformation("Job {JobName} deleted successfully. Result: {Result}", jobName, result);

                SerilogLogger.LogInfo($"定时任务 {task.Name} 删除成功");
                return result;
            }
            catch (Exception ex)
            {
                //_logger.LogError(ex, "Failed to delete job {JobName}", jobName);

                SerilogLogger.LogError($"定时任务 {task.Name} 删除失败 {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 获取所有 JobKeys
        /// </summary>
        public async Task<IReadOnlyCollection<JobKey>> GetAllJobKeysAsync()
        {
            var scheduler = await _schedulerFactory.GetScheduler();
            return await scheduler.GetJobKeys(GroupMatcher<JobKey>.AnyGroup());
        }
    }
}